{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "aeafd728-6947-4386-b332-685cb0c89827",
   "metadata": {},
   "source": [
    "# Advanced visualization tutorial \n",
    "\n",
    "Next to the high level plotting function `mendeleev.vis.periodic_table`, `mendeleev` offers two lower level functions that give you more control over the result. There are two plotting backends supported:\n",
    "\n",
    "1. [Plotly](https://plotly.com/) (default)\n",
    "2. [Bokeh](http://bokeh.pydata.org/en/latest/)\n",
    "\n",
    "## Note\n",
    "\n",
    "Depending on your environment being the classic jupyter notebook or jupyterlab you might have to do additional configuration steps, so if you're not getting expected results see plotly of bokeh documentation.\n",
    "\n",
    "## Accessing lower level plotting functions\n",
    "\n",
    "There are two plotting functions, one for each of the backends:\n",
    "\n",
    "- `periodic_table_plotly` in `mendeleev.vis.plotly`\n",
    "- `periodic_table_bokeh` in `mendeleev.vis.bokeh`\n",
    "\n",
    "that you can use to customize the visualizations even further.\n",
    "\n",
    "Both functions take the same keyword arguments as the `periodic_table` function but the also require a `DataFrame` with periodic table data. That dataframe needs to have `x` and `y` columns for each element that play the role of coordinates. You can get the default data using the `create_vis_dataframe` function. Let's start with an example using the `plotly` backend."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8722f724-3a07-440c-b529-fb4144a9d8a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "from mendeleev.vis import create_vis_dataframe, periodic_table_plotly"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e05e9c9e-fcdb-406d-bb98-e9d4b601cafe",
   "metadata": {},
   "source": [
    "The function has only one required argument which is the data itself."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "987a8b97-88b2-4e07-b8a1-ee6903a1042e",
   "metadata": {},
   "outputs": [],
   "source": [
    "elements = create_vis_dataframe()\n",
    "periodic_table_plotly(elements)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ad657cb-eac9-4a1e-9f0b-1d6be4adde16",
   "metadata": {},
   "source": [
    "## Custom coloring scheme"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ccda6e3-89ec-4168-89c0-935a16583f67",
   "metadata": {},
   "source": [
    "To apply a custom color scheme you can assign color to all the elments in the `DataFrame`. This can be done by creating a custom column in the `DataFrame` and then using `colorby` argument to specify which column contains colors. Let's try to color the elements according to the block they belong to."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa28ee38-9f1a-4f4a-828d-50b941f1494f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import seaborn as sns\n",
    "from matplotlib import colors\n",
    "\n",
    "blockcmap = {\n",
    "    b: colors.rgb2hex(c)\n",
    "    for b, c in zip([\"s\", \"p\", \"d\", \"f\"], sns.color_palette(\"deep\"))\n",
    "}\n",
    "\n",
    "elements[\"block_color\"] = elements[\"block\"].map(blockcmap)\n",
    "periodic_table_plotly(elements, colorby=\"block_color\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91a59d15-bdf7-4234-ba39-2e90fcf29d33",
   "metadata": {},
   "source": [
    "## Custom properties\n",
    "\n",
    "You can also visualize custom properties using [pandas](http://pandas.pydata.org/)' awesome methods for manipulating data. For example let's consider the difference of electronegativity between every element and the Oxygen atom. To calculate the values we will use Allen scale this time and call our new value `ENX-ENO`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03d7be92-ceea-4778-8ecf-ba0dbee8f697",
   "metadata": {},
   "outputs": [],
   "source": [
    "elements.loc[:, \"ENX-ENO\"] = (\n",
    "    elements.loc[elements[\"symbol\"] == \"O\", \"en_allen\"].values\n",
    "    - elements.loc[:, \"en_allen\"]\n",
    ")\n",
    "\n",
    "periodic_table_plotly(\n",
    "    elements,\n",
    "    attribute=\"ENX-ENO\",\n",
    "    colorby=\"attribute\",\n",
    "    cmap=\"viridis\",\n",
    "    title=\"Allen Electronegativity wrt. Oxygen\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ad2bd4b-6abe-4f74-958f-91f8ce60aa89",
   "metadata": {},
   "source": [
    "As a second example let's consider a difference between the `covalent_radius_slater` and `covalent_radius_pyykko` values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d32fdac2-a417-4034-9bf3-0a40883ad00a",
   "metadata": {},
   "outputs": [],
   "source": [
    "elements[\"cov_rad_diff\"] = (\n",
    "    elements[\"atomic_radius\"] - elements[\"covalent_radius_pyykko\"]\n",
    ")\n",
    "\n",
    "periodic_table_plotly(\n",
    "    elements,\n",
    "    attribute=\"cov_rad_diff\",\n",
    "    colorby=\"attribute\",\n",
    "    title=\"Covalent Radii Difference\",\n",
    "    cmap=\"viridis\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed6c8eaa-e77b-4587-8d91-f33f6324ff0b",
   "metadata": {},
   "source": [
    "## Bokeh backend"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "097da132-5745-47d0-b0fa-506d5728c58e",
   "metadata": {},
   "source": [
    "We can also use the `Bokeh` backed in the same way but we need to take a few extra steps to render the result in a notebook"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed1a108c-5787-4f64-b127-3968e68b19b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bokeh.plotting import show, output_notebook\n",
    "from mendeleev.vis import periodic_table_bokeh"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0402e773-1a1b-4e0a-9a84-37ba32d6467a",
   "metadata": {},
   "source": [
    "First we need to enable notebook output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8742b638-28db-43be-9dc4-fb5f34214bcd",
   "metadata": {},
   "outputs": [],
   "source": [
    "output_notebook()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d2e4e013-bf8d-4b06-9d93-5c762a74e87e",
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = periodic_table_bokeh(elements)\n",
    "show(fig)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "486993bb-d22f-4d00-8e32-9ae470eb9a81",
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = periodic_table_bokeh(elements, attribute=\"atomic_radius\", colorby=\"attribute\")\n",
    "show(fig)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
